package com.jdj.framework.core.base.utils;

import com.google.common.collect.Maps;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 文件操作工具类
 *
 * @author caijinbang
 * @date 2019-04-13 15:28
 */
public class FileUtils {
    private static int readSize = 1024;

    private static String charsetName = "UTF-8";

    private static Logger logger = LoggerFactory.getLogger(FileUtils.class);

    /**
     * 设置文本的字符集
     *
     * @param charsetName
     */
    public static void setCharsetName(String charsetName) {
        FileUtils.charsetName = charsetName;
    }

    /**
     * 设置读取文件的buffer大小
     *
     * @param readSize
     */
    public static void setReadSize(int readSize) {
        FileUtils.readSize = readSize;
    }

    /**
     * 截取文件名的扩展名
     */
    public static String getFileExtension(String fileName) {
        if (fileName.lastIndexOf(".") > 0 && fileName.lastIndexOf(".") < fileName.length() - 1) {
            return fileName.substring(fileName.lastIndexOf(".") + 1);
        } else {
            return null;
        }
    }

    /**
     * 获得完整路径
     *
     * @param path
     * @param name
     * @return String
     */
    public static String getFullPathFileName(String path, String name) {
        if ("//".equals(name.substring(0, 2))) {
            return name.substring(2, name.length());
        } else {
            if (path.charAt(path.length() - 1) == '/') {
                if (name.charAt(0) == '/') {
                    return path.substring(0, path.length() - 1) + name;
                } else {
                    return path + name;
                }
            } else {
                if (name.charAt(0) == '/') {
                    return path + name;
                } else {
                    return path + '/' + name;
                }
            }
        }
    }

    /**
     * 将文本写入到文件中
     *
     * @param filename
     * @param text
     * @throws IOException
     */
    public static void writeText(String filename, String text) throws IOException {
        FileOutputStream f = null;
        try {
            f = new FileOutputStream(filename);
            writeText(f, text);
        } finally {
            try {
                if (f != null) {
                    f.close();
                }
            } catch (IOException e) {
                logger.debug("write Text into file error", e);
            }
        }
    }

    /**
     * 将文本写入到文件中
     *
     * @param out
     * @param text
     * @throws IOException
     */
    public static void writeText(OutputStream out, String text) throws IOException {
        OutputStreamWriter osWriter = null;
        BufferedWriter writer = null;
        try {
            osWriter = new OutputStreamWriter(out, charsetName);
            writer = new BufferedWriter(osWriter);
            writer.write(text);
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                logger.debug("write Text into file error", e);
            }
            try {
                if (osWriter != null) {
                    osWriter.close();
                }
            } catch (IOException e) {
                logger.debug("write Text into file error", e);
            }
        }
    }

    /**
     * 读取文件到String
     *
     * @param filename
     * @return String
     * @throws IOException
     */
    public static String readText(String filename) throws IOException {
        FileInputStream f = null;
        try {
            f = new FileInputStream(filename);
            return readText(f);
        } finally {
            try {
                if (f != null) {
                    f.close();
                }
            } catch (IOException e) {
                logger.debug("read Text from file error", e);
            }
        }
    }

    /**
     * 读取文件到String
     *
     * @param in
     * @return String
     * @throws IOException
     */
    public static String readText(InputStream in) throws IOException {
        StringBuffer rtn = new StringBuffer();
        if (readSize <= 0) {
            readSize = 1024;
        }
        int realReadSize = readSize;
        byte[] data = new byte[readSize];

        while (realReadSize > 0) {
            realReadSize = in.read(data);
            if (realReadSize > 0) {
                rtn.append(new String(data, 0, realReadSize, charsetName));
            }
        }
        if (rtn.length() > 0) {
            return rtn.toString();
        } else {
            return null;
        }
    }

    /**
     * 删除文件或目录下所有文件
     *
     * @param path
     */
    public static void deleteAll(String path) {
        deleteAll(new File(path));
    }

    /**
     * 删除文件或目录下所有文件
     *
     * @param path
     */
    public static void deleteAll(File path) {
        if (!path.exists()) {
            return;
        }
        if (path.isFile()) {
            path.delete();
            return;
        }
        File[] files = path.listFiles();
        for (int i = 0; i < files.length; i++) {
            deleteAll(files[i]);
        }
        path.delete();
    }

    /**
     * 列出所有当前层的文件和目录
     *
     * @param dir
     *            目录名称
     * @return fileList 列出的文件和目录
     */
    public static File[] ls(String dir) {
        return new File(dir).listFiles();
    }

    /**
     * 根据需要创建文件夹
     *
     * @param dirPath
     *            文件夹路径
     * @param del
     *            存在文件夹是否删除
     */
    public static void mkdir(String dirPath, boolean del) {
        File dir = new File(dirPath);
        if (dir.exists()) {
            if (del) {
                dir.delete();
            } else {
                return;
            }
        }
        dir.mkdirs();
    }

    /**
     * 删除文件和目录
     *
     * @param path
     * @throws Exception
     */
    public static void rm(String path) throws Exception {
        logger.debug("需要删除的文件: " + path);
        File file = new File(path);
        if (!file.exists()) {
            if (logger.isWarnEnabled()) {
                logger.warn("文件<" + path + ">不存在");
            }
            return;
        }
        if (file.isDirectory()) {
            File[] fileList = file.listFiles();
            if (fileList == null || fileList.length == 0) {
                file.delete();
            } else {
                for (File _file : fileList) {
                    rm(_file.getAbsolutePath());
                }
            }
            file.delete();
        } else {
            file.delete();
        }
    }

    /**
     * 移动文件
     *
     * @param source
     *            源文件
     * @param target
     *            目标文件
     * @param cache
     *            文件缓存大小
     * @throws Exception
     */
    public static void mv(String source, String target, int cache) throws Exception {
        if (source.trim().equals(target.trim())) {
            return;
        }
        byte[] cached = new byte[cache];
        FileInputStream fromFile = new FileInputStream(source);
        FileOutputStream toFile = new FileOutputStream(target);
        while (fromFile.read(cached) != -1) {
            toFile.write(cached);
        }
        toFile.flush();
        toFile.close();
        fromFile.close();
        new File(source).deleteOnExit();
    }

    /**
     * 把属性文件转换成Map
     *
     * @param propertiesFile
     * @return
     * @throws Exception
     */
    public static final Map<String, String> getPropertiesMap(String propertiesFile) throws Exception {
        Properties properties = new Properties();
        FileInputStream inputStream = new FileInputStream(propertiesFile);
        properties.load(inputStream);
        Map<String, String> map = new HashMap<String, String>();
        Set<Object> keySet = properties.keySet();
        for (Object key : keySet) {
            map.put((String) key, properties.getProperty((String) key));
        }
        return map;
    }

    /**
     * 获取属性map
     * @param clazz
     * @param fileName
     * @return
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public static final Map<String, String> getPropertiesMap(Class clazz, String fileName) throws Exception {
        Properties properties = new Properties();
        InputStream inputStream = clazz.getResourceAsStream(fileName);
        if (inputStream == null) {
            inputStream = clazz.getClassLoader().getResourceAsStream(fileName);
        }
        return getPropertiesMap(properties,inputStream);
    }

    /**
     * 把属性文件转换成Map
     *
     * @param inputStream
     * @return
     * @throws Exception
     */
    public static final Map<String, String> getPropertiesMap(InputStream inputStream) throws Exception {
        Properties properties = new Properties();
        return getPropertiesMap(properties,inputStream);
    }

    /**
     * 把属性文件转换成Map
     *
     * @param inputStream
     * @return
     * @throws Exception
     */
    public static final Map<String, String> getPropertiesMap(Properties properties,InputStream inputStream) throws Exception {
        Map<String, String> map = Maps.newHashMap();
        if (properties == null) {
            properties = new Properties();
        }
        properties.load(inputStream);
        Set<Object> keySet = properties.keySet();
        for (Object key : keySet) {
            map.put((String) key, properties.getProperty((String) key));
        }
        return map;
    }


    /**
     * 获取资源文件流
     *
     * @param clazz
     * @param name
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static InputStream getResourceAsStream(Class clazz, String name) {
        try {
            InputStream inputStream = clazz.getResourceAsStream(name);
            if (inputStream == null) {
                inputStream = clazz.getClassLoader().getResourceAsStream(name);
            }
            return inputStream;
        } catch (Exception e) {
            logger.warn("获取资源文件失败", e);
            return null;
        }
    }
}
